<?php


namespace App\Service;


use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class WeiSendAuto
{
    /**
     * 微信模拟扫码登录 mp.weixin.qq.com
     *
     * $arr = array(
     *   'account'  => '***',
     *   'password' => '****',
     *   'key'    => "tmall",
     * );
     * $w =  new WeiSendAuto();
     * $w->init($arr);
     * if(!$w->getToken()){
     *   die("NOT TOKEN!");
     * }
     */

    //--------------------------------------------------------LOGIN START
    private $_apis         = [
        "host"        => "https://mp.weixin.qq.com",
        "login"       => "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=startlogin",
        "qrcode"      => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=getqrcode¶m=4300",
        "loginqrcode" => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=ask&token=&lang=zh_CN&f=json&ajax=1",
        "loginask"    => "https://mp.weixin.qq.com/cgi-bin/loginqrcode?action=ask&token=&lang=zh_CN&f=json&ajax=1&random=",
        "loginauth"   => "https://mp.weixin.qq.com/cgi-bin/loginauth?action=ask&token=&lang=zh_CN&f=json&ajax=1",
        "bizlogin"    => "https://mp.weixin.qq.com/cgi-bin/bizlogin?action=login&lang=zh_CN",
    ];
    private $_redirect_url = "";
    private $_key          = "";
    private $_error        = "";

    // 获取 token
    public function getToken()
    {
        return Cache::get("token_{$this->_key}");
    }

    // 保存token
    public function setToken($token)
    {
        Cache::set("token_{$this->_key}", $token);
    }

    // 初始化
    public function init($options)
    {
        if(!isset($options["key"])){
            die("Key is Null!");
        }

        $this->_key = $options["key"];
        if($this->getToken()){
            echo("HAS Token !");

            return;
        }

        //尼玛，先要获取首页!!!
        $this->fetch("https://mp.weixin.qq.com/", "", "text");
        $this->_log("start login!!");
        $this->start_login($options);
    }


    // 获取错误信息
    public function getError()
    {
        return $this->_error;
    }

    // 开始登录
    private function start_login($options)
    {
        $_res = $this->_login($options["account"], $options["password"]);
        if(!$_res["status"]){
            $this->_log($_res["info"]);

            return;
        }

        $_post = ["refer" => $this->_redirect_url];
        //保存二维码
        $this->_saveQRcode();
        $_ask_api = $this->_apis["loginask"];
        $_index   = 1;
        while(true){
            /* if($_index>60){
                break;
            }*/
            $_res    = $this->fetch($_ask_api.$this->getWxRandomNum(), $_post);
            $_status = $_res["status"];
            if($_status == 1){
                if($_res["user_category"] == 1){
                    $_ask_api = $this->_apis["loginauth"];
                } else{
                    $this->_log("Login success");
                    break;
                }
            } elseif($_status == 4){
                $this->_log("已经扫码");
            } elseif($_status == 2){
                $this->_log("管理员拒绝");
                break;
            } elseif($_status == 3){
                $this->_log("登录超时");
                break;
            } else{
                if($_ask_api == $this->_apis["loginask"]){
                    $this->_log("请打开test.jpg，用微信扫码");
                } else{
                    $this->_log("等待确认");
                }
            }
            sleep(2);
            $_index++;
        }

        /*if($_index>=60){
          $this->_log("U亲，超时了");
          return;
        }*/
        $this->_log("开始验证");
        $_post["post"]  = ["lang" => "zh_CN", "f" => "json", "ajax" => 1, "random" => $this->getWxRandomNum(), "token" => ""];
        $_post["refer"] = $this->_redirect_url;
        // 验证
        $_res = $this->fetch($this->_apis["bizlogin"], $_post);
        $this->_log(print_r($_res, true));
        if($_res["base_resp"]["ret"] != 0){
            $this->_log("error = ".$_res["base_resp"]["err_msg"]);

            return;
        }

        $redirect_url = $_res["redirect_url"];//跳转路径
        if(preg_match('/token=([\d]+)/i', $redirect_url, $match)){//获取cookie
            $this->setToken($match[1]);
        }

        $this->_log("验证成功,token: ".$this->getToken());
    }


    /**
     * @param $url
     * @param null $_post
     * @param string $data_type
     * @return mixed
     * $_post= ["post"=>[],"refer"=>"",cookiefile='']
     */
    protected function fetch($url, $_post = null, $data_type = 'json')
    {
        $ch        = curl_init();
        $useragent = isset($_post['useragent']) ? $_post['useragent'] : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
        //curl_setopt( $ch, CURLOPT_HTTPHEADER, $this->_headers); //设置HTTP头字段的数组
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_AUTOREFERER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_POST, isset($_post['post']));
        if(isset($_post['post'])){
            curl_setopt($ch, CURLOPT_POSTFIELDS, $_post['post']);
        }
        if(isset($_post['refer'])){
            curl_setopt($ch, CURLOPT_REFERER, $_post['refer']);
        }
        curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (isset($_post['timeout']) ? $_post['timeout'] : 5));
        curl_setopt($ch, CURLOPT_COOKIEJAR, (isset($_post['cookiefile']) ? $_post['cookiefile'] : $this->_getCookieFile()));
        curl_setopt($ch, CURLOPT_COOKIEFILE, (isset($_post['cookiefile']) ? $_post['cookiefile'] : $this->_getCookieFile()));

        $result = curl_exec($ch);
        curl_close($ch);
        if($data_type == 'json'){
            $result = json_decode($result, true);
        }

        return $result;
    }

    //--------------------------------------------------------

    // 执行登录
    private function _login($_username, $_password)
    {
        $_post = [
            "refer" => "https://mp.weixin.qq.com",
            "post"  => array(
                'username' => $_username,
                'pwd'      => md5($_password),
                'f'        => 'json',
                'imgcode'  => "",
            ),
        ];
        $_res  = $this->fetch($this->_apis["login"], $_post);
        if($_res["base_resp"]["ret"] !== 0){
            return $this->return_false($_res["base_resp"]["err_msg"]);
        }

        $this->_redirect_url = "https://mp.weixin.qq.com".$_res["redirect_url"];//跳转路径

        return true;
    }

    // 获取随机数
    private function getWxRandomNum()
    {
        return "0.".mt_rand(1000000000000000, 9999999999999999);
    }

    // 获取cookie文件
    private function _getCookieFile()
    {
        $path = app()->basePath().'/public/static/cookie/';

        return $path."cookie_{$this->_key}.text";
    }

    // 获取二维码文件
    private function _getSavePath()
    {
        $path = app()->basePath().'/public/static/cookie/';

        return $path."qrcode_{$this->_key}.png";
    }

    // 日志
    private function _log($msg)
    {
        Log::debug("[微信调度:".date("Y-m-d H:i:s")."] ======: {$msg}");
    }

    //下载二维码
    private function _saveQRcode()
    {
        $_post = ["refer" => $this->_redirect_url];
        $_res  = $this->fetch($this->_apis["qrcode"], $_post, "text");
        $fp = fopen($this->_getSavePath(), "wb+") or die("open fails");
        fwrite($fp, $_res) or die("fwrite fails");
        fclose($fp);
    }

    // 错误
    private function return_false($error)
    {
        $this->error = $error;

        return false;
    }

}


